-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[libc++] Fold __search_substring into _Traits::find in case the second string has length 1 #160076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Fold __search_substring into _Traits::find in case the second string has length 1 #160076
Conversation
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
dd1885a to
f188376
Compare
|
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesFull diff: https://github.com/llvm/llvm-project/pull/160076.diff 3 Files Affected:
diff --git a/libcxx/include/__string/char_traits.h b/libcxx/include/__string/char_traits.h
index 86c92477cbfeb..8292750919427 100644
--- a/libcxx/include/__string/char_traits.h
+++ b/libcxx/include/__string/char_traits.h
@@ -369,6 +369,13 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT* __searc
if (__len1 < __len2)
return __last1;
+ if (__builtin_constant_p(__len2 == 1) && __len2 == 1) {
+ auto __res = _Traits::find(__first1, __len1, *__first2);
+ if (__res == nullptr)
+ return __last1;
+ return __res;
+ }
+
// First element of __first2 is loop invariant.
_CharT __f2 = *__first2;
while (true) {
diff --git a/libcxx/test/benchmarks/containers/string.bench.cpp b/libcxx/test/benchmarks/containers/string.bench.cpp
index 966775d31a8cf..68f596b1be62a 100644
--- a/libcxx/test/benchmarks/containers/string.bench.cpp
+++ b/libcxx/test/benchmarks/containers/string.bench.cpp
@@ -60,6 +60,45 @@ static void BM_StringFindMatch2(benchmark::State& state) {
}
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);
+static void BM_string_literal(benchmark::State& state) {
+ std::string s;
+
+ for (int i = 0; i < state.range(0); i++)
+ s += 'a';
+
+ s += 'b';
+
+ benchmark::DoNotOptimize(s.data());
+ benchmark::ClobberMemory();
+ size_t pos;
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(pos = s.find("b")); // "b" is a string literal, it should be longer
+ benchmark::ClobberMemory();
+ }
+}
+
+BENCHMARK(BM_string_literal)->RangeMultiplier(2)->Range(8, 8 << 10);
+
+static void BM_char_literal(benchmark::State& state) {
+ std::string s;
+
+ for (int i = 0; i < state.range(0); i++)
+ s += 'a';
+
+ s += 'b';
+
+ benchmark::DoNotOptimize(s.data());
+ benchmark::ClobberMemory();
+ size_t pos;
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(pos = s.find('b')); // 'b' is a char literal, it should be faster
+ benchmark::ClobberMemory();
+ }
+}
+BENCHMARK(BM_char_literal)->RangeMultiplier(2)->Range(8, 8 << 10);
+
static void BM_StringCtorDefault(benchmark::State& state) {
for (auto _ : state) {
std::string Default;
diff --git a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
index 60ed469ce991b..4aa4a3f339142 100644
--- a/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp
@@ -43,14 +43,17 @@ TEST_CONSTEXPR_CXX20 void test0() {
test(S(""), S("abcdeabcde"), 1, S::npos);
test(S(""), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcde"), S(""), 0, 0);
+ test(S("abcde"), S("a"), 0, 0);
test(S("abcde"), S("abcde"), 0, 0);
test(S("abcde"), S("abcdeabcde"), 0, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 0, S::npos);
test(S("abcde"), S(""), 1, 1);
+ test(S("abcde"), S("a"), 1, S::npos);
test(S("abcde"), S("abcde"), 1, S::npos);
test(S("abcde"), S("abcdeabcde"), 1, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcde"), S(""), 2, 2);
+ test(S("abcde"), S("a"), 2, S::npos);
test(S("abcde"), S("abcde"), 2, S::npos);
test(S("abcde"), S("abcdeabcde"), 2, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 2, S::npos);
@@ -59,58 +62,72 @@ TEST_CONSTEXPR_CXX20 void test0() {
test(S("abcde"), S("abcdeabcde"), 4, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 4, S::npos);
test(S("abcde"), S(""), 5, 5);
+ test(S("abcde"), S("a"), 5, S::npos);
test(S("abcde"), S("abcde"), 5, S::npos);
test(S("abcde"), S("abcdeabcde"), 5, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 5, S::npos);
test(S("abcde"), S(""), 6, S::npos);
+ test(S("abcde"), S("a"), 6, S::npos);
test(S("abcde"), S("abcde"), 6, S::npos);
test(S("abcde"), S("abcdeabcde"), 6, S::npos);
test(S("abcde"), S("abcdeabcdeabcdeabcde"), 6, S::npos);
test(S("abcdeabcde"), S(""), 0, 0);
+ test(S("abcdeabcde"), S("a"), 0, 0);
test(S("abcdeabcde"), S("abcde"), 0, 0);
test(S("abcdeabcde"), S("abcdeabcde"), 0, 0);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 0, S::npos);
test(S("abcdeabcde"), S(""), 1, 1);
+ test(S("abcdeabcde"), S("a"), 1, 5);
test(S("abcdeabcde"), S("abcde"), 1, 5);
test(S("abcdeabcde"), S("abcdeabcde"), 1, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcdeabcde"), S(""), 5, 5);
+ test(S("abcdeabcde"), S("a"), 5, 5);
test(S("abcdeabcde"), S("abcde"), 5, 5);
test(S("abcdeabcde"), S("abcdeabcde"), 5, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 5, S::npos);
test(S("abcdeabcde"), S(""), 9, 9);
+ test(S("abcdeabcde"), S("a"), 9, S::npos);
test(S("abcdeabcde"), S("abcde"), 9, S::npos);
test(S("abcdeabcde"), S("abcdeabcde"), 9, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 9, S::npos);
test(S("abcdeabcde"), S(""), 10, 10);
+ test(S("abcdeabcde"), S("a"), 10, S::npos);
test(S("abcdeabcde"), S("abcde"), 10, S::npos);
test(S("abcdeabcde"), S("abcdeabcde"), 10, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 10, S::npos);
test(S("abcdeabcde"), S(""), 11, S::npos);
+ test(S("abcdeabcde"), S("a"), 11, S::npos);
test(S("abcdeabcde"), S("abcde"), 11, S::npos);
test(S("abcdeabcde"), S("abcdeabcde"), 11, S::npos);
test(S("abcdeabcde"), S("abcdeabcdeabcdeabcde"), 11, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 0, 0);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 0, 0);
test(S("abcdeabcdeabcdeabcde"), S(""), 1, 1);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 1, 5);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 1, 5);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 1, 5);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 1, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 10, 10);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 10, 10);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 10, 10);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 10, 10);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 10, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 19, 19);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 19, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 20, 20);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 20, S::npos);
test(S("abcdeabcdeabcdeabcde"), S(""), 21, S::npos);
+ test(S("abcdeabcdeabcdeabcde"), S("a"), 21, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcde"), 21, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcde"), 21, S::npos);
test(S("abcdeabcdeabcdeabcde"), S("abcdeabcdeabcdeabcde"), 21, S::npos);
|
…d string has length 1
f188376 to
57ff008
Compare
…d string has length 1 (llvm#160076) Apple M4: ``` Benchmark Baseline Candidate Difference % Difference ----------------------------------------------------------- ---------- ----------- ------------ -------------- BM_string_literal/1024 16.99 16.79 -0.21 -1.21 BM_string_literal/128 3.44 3.34 -0.10 -2.88 BM_string_literal/16 1.80 1.69 -0.11 -5.93 BM_string_literal/2048 38.44 38.38 -0.07 -0.17 BM_string_literal/256 5.77 5.65 -0.12 -2.02 BM_string_literal/32 2.03 1.92 -0.11 -5.44 BM_string_literal/4096 73.92 73.74 -0.18 -0.25 BM_string_literal/512 9.49 9.41 -0.08 -0.84 BM_string_literal/64 2.59 2.45 -0.14 -5.38 BM_string_literal/8 1.79 1.69 -0.11 -5.90 BM_string_literal/8192 132.09 131.81 -0.28 -0.21 ```
|
@philnik777 we (at google) have bisected a performance regression caused by this change in the https://github.com/abseil/abseil-cpp/blob/master/absl/strings/string_view_benchmark.cc which benchmarks the standard Interestingly we only see the regressions on ARM servers:
The regression is computed as: I don't have an Apple M4 (which is also ARM) readily available to check if the regression reproduces there. Would it be possible for you to check or maybe replicate the LATER EDIT: to clarify, baseline is the revision previous to this one. |
Apple M4: